package com.rowline.admin.module.study.reflect;


import com.rowline.admin.module.study.variable.Dog;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * ClassName:reflectTest
 * Created by 245167
 * on 2017/10/31  31:24
 * description:
 */
public class ReflectTest {

    public static void main(String[] args) {

        /**
         * 1.什么是Class类？
         */
        Dog dog = new Dog();
        // 第一种方式，我们任何一个类都有一个隐含的静态成员变量class
        Class dog1 = Dog.class;
        // 第二种方式，已知了该类的对象的情况下通过getClass方法获取
        Class dog2 = dog.getClass();
        // 第三种方式，已知类的全称
        Class dog3 = null;
        try {
            dog3 = Class.forName("com.rowline.admin.module.study.variable.Dog");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("dog1 == dog2 is " + (dog1 == dog2)); // true
        System.out.println("dog1 == dog3 is " + (dog1 == dog3)); // true
        // 说明一个类只可能是Class类的一个实例对象。


        System.out.println("=======================================");
        /**
         * 2.可以通过类的类类型创建该类的对象实例
         */
        Dog dog4 = null;
        try {
            dog4 = (Dog) dog1.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        dog4.print();

        System.out.println("=======================================");
        /**
         * 通过方法的反射得到该类的名称步骤：
         1.获取该类的类类型
         2.通过类类型获取类的方法（getMethods()）
         3.循环遍历所获取到的方法
         4.通过这些方法的getReturnType()得到返回值类型的类类型，又通过该类类型得到返回值类型的名字
         5.getName()得到方法的名称，getParameterTypes()获取这个方法里面的参数类型的类类型。
         */

        //Class dog1 = Dog.class;
        System.out.println("Dog的类名称是：" + dog1.getName());

        Method[] methods = dog1.getMethods();
        String method = null;
        for(int i=0;i<methods.length;i++){
            Class returnType = methods[i].getReturnType();
            method = returnType.getName() + " " + methods[i].getName() + "( ";
            Class[] paramTypes = methods[i].getParameterTypes();
            if(0 < paramTypes.length){
                for (Class class1 : paramTypes) {
                    method = method + class1.getName() + ",";
                }
            }
            method = method + " )";
            System.out.println(method);
        }


        System.out.println("=======================================");

        /***********成员变量的反射***********/

        // getFields() 方法获取的所有的public的成员变量的信息
        Field[] fields = dog1.getFields();
        for(int i=0;i<fields.length;i++){
            System.out.println("getFields() 成员变量【"+ i + "】:" + fields[i]);
        }

        // getDeclaredFields 获取所有自己声明的成员变量的信息
        Field[] fields2 = dog1.getDeclaredFields();
        for (Field field : fields2) {
            //得到成员变量的类型的类类型
            Class fieldType = field.getType();
            String typeName = fieldType.getName();
            //得到成员变量的名称
            String fieldName = field.getName();
            System.out.println(typeName + " " + fieldName);
        }

        /**
            * 首先构造函数也是对象，是java.lang.Constructor类的对象
            * 也就是java.lang. Constructor中封装了构造函数的信息
            * 和前面说到的一样，它也有两个方法：
            * getConstructors()方法获取所有的public的构造函数
            * getDeclaredConstructors()方法得到所有的自己声明的构造函数
            */
        //Constructor[] cs = dog1.getConstructors();
        Constructor[] cs = dog1.getDeclaredConstructors();
        String constructorDesc = null;
        for (Constructor constructor : cs) {
            //我们知道构造方法是没有返回值类型的，但是我们可以：
            constructorDesc = constructor.getName() + "(";
            //获取构造函数的参数列表》》得到的是参数列表的类类型
            Class[] paramTypes = constructor.getParameterTypes();
            for (Class class1 : paramTypes) {
                constructorDesc = constructorDesc + class1.getName() + ",";
            }
            constructorDesc = constructorDesc + ")";
            System.out.println("constructor ==> " + constructorDesc);
        }

    }


}
